package com.pioneer.web.sale.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pioneer.common.utils.SecurityUtils;
import com.pioneer.web.sale.domain.SalContract;
import com.pioneer.web.sale.domain.SalContractBody;
import com.pioneer.web.sale.domain.SalOrder;
import com.pioneer.web.sale.domain.SalOrderBody;
import com.pioneer.web.sale.mapper.SalOrderBodyMapper;
import com.pioneer.web.sale.mapper.SalOrderMapper;
import com.pioneer.web.sale.service.ISalOrderService;
import com.pioneer.web.stock.service.IStoInoutService;
import jakarta.annotation.Resource;
import org.apache.ibatis.executor.BatchResult;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * SalOrderServiceImpl
 *
 * @author hlm
 * @date 2025-04-30 15:10:02
 */
@Service
public class SalOrderServiceImpl extends ServiceImpl<SalOrderMapper, SalOrder> implements ISalOrderService {

    @Resource
    private SalOrderBodyMapper orderBodyMapper;

    @Resource
    private IStoInoutService inoutService;

    @Override
    public boolean genOrderByContract(SalContract contract) {
        // 构建销售订单对象
        SalOrder order = new SalOrder();
        order.setOrderCode(genOrderCode());
        order.setOrderName(contract.getContractName() + "-销售订单");
        order.setSourceId(contract.getContractId());
        order.setTotal(contract.getTotal());
        order.setApproveStatus("2");
        order.setApprover(SecurityUtils.getLoginUser().getUsername());
        order.setApproveTime(LocalDateTime.now());
        // 1.保存销售订单
        boolean ret = save(order);
        if (!ret) {
            throw new RuntimeException("生成销售订单失败");
        }
        // 销售订单子表集合
        List<SalOrderBody> orderBodyList = new ArrayList<>();
        // 获取销售合同子表信息
        List<SalContractBody> contractBodyList = contract.getContractBodyList();
        contractBodyList.forEach(contractBody -> {
            // 构建销售订单子表对象
            SalOrderBody orderBody = new SalOrderBody();
            orderBody.setOrderId(order.getOrderId());
            orderBody.setSourceRowid(contractBody.getContractBodyId());
            orderBody.setInventoryId(contractBody.getInventoryId());
            orderBody.setOrderNumber(contractBody.getSaleNumber());
            orderBody.setOrderPrice(contractBody.getSalePrice());
            orderBody.setOrderTotal(contractBody.getSaleTotal());
            orderBodyList.add(orderBody);
        });
        // 2.批量保存销售订单子表
        List<BatchResult> results = orderBodyMapper.insert(orderBodyList);
        if (CollUtil.isEmpty(results)) {
            throw new RuntimeException("生成销售订单子表失败");
        }
        // 设置销售订单子表信息
        order.setOrderBodyList(orderBodyList);
        // 自动生成一张销售出库单
        boolean inoutRet = inoutService.genInoutByOrder(order);
        if (!inoutRet) {
            throw new RuntimeException("生成下游单据[销售出库单]失败");
        }
        return true;
    }

    @Override
    public boolean delOrderByContract(SalContract salContract) {
        LambdaQueryWrapper<SalOrder> query = Wrappers.lambdaQuery();
        query.eq(SalOrder::getSourceId, salContract.getContractId());
        SalOrder order = getOne(query);
        if (order != null) {
            if (!"0".equals(order.getApproveStatus())) {
                throw new RuntimeException("下游单据[销售订单]已被提交或审批，不能弃审");
            }
            // 1.删除销售订单子表 delete from sal_order_body where order_id = ?
            LambdaQueryWrapper<SalOrderBody> bodyDelete = Wrappers.lambdaQuery();
            bodyDelete.eq(SalOrderBody::getOrderId, order.getOrderId());
            int bodyRet = orderBodyMapper.delete(bodyDelete);
            if (bodyRet <= 0) {
                throw new RuntimeException("删除销售订单子表失败");
            }
            // 2.删除销售订单 delete from sal_order where order_id = ?
            boolean ret = removeById(order.getOrderId());
            if (!ret) {
                throw new RuntimeException("删除销售订单失败");
            }
        }
        return true;
    }

    @Override
    public SalOrder getOrderById(Long orderId) {
        // 方法1
//        // 根据销售订单ID查询详情
//        SalOrder salOrder = getById(orderId);
//        // 根据销售订单ID查询子表详情
//        LambdaQueryWrapper<SalOrderBody> bodyQuery = Wrappers.lambdaQuery();
//        bodyQuery.eq(SalOrderBody::getOrderId, orderId);
//        List<SalOrderBody> bodyList = orderBodyMapper.selectList(bodyQuery);
//        salOrder.setOrderBodyList(bodyList);
//        return salOrder;

        // 方法2
        return getBaseMapper().getOrderById(orderId);
    }

    @Override
    public boolean updateOrderById(SalOrder order) {
        SalOrder salOrder = getById(order.getOrderId());
        if (salOrder == null) {
            throw new RuntimeException("单据不存在，请刷新后重新");
        }
        // 校验销售订单状态
        if (!"0".equals(salOrder.getApproveStatus())) {
            throw new RuntimeException("只有订单状态为初始的数据才可以修改");
        }
        // 校验销售订单子表集合
        List<SalOrderBody> orderBodyList = order.getOrderBodyList();
        if (CollUtil.isEmpty(orderBodyList)) {
            throw new RuntimeException("销售订单子表信息不能为空");
        }
        // 订单总金额
        BigDecimal total = BigDecimal.ZERO;
        // 需要修改的销售订单子表集合
        List<SalOrderBody> updateOrderBodyList = new ArrayList<>();
        // 循环提交的子表集合
        for (int i = 0; i < orderBodyList.size(); i++) {
            SalOrderBody body = orderBodyList.get(i);
            Long inventoryId = body.getInventoryId();
            if (inventoryId == null) {
                throw new RuntimeException("第" + (i + 1) + "行的存货管理不能为空，请选择");
            }
            BigDecimal orderNumber = body.getOrderNumber();
            if (orderNumber == null || orderNumber.doubleValue() <= 0) {
                throw new RuntimeException("第" + (i + 1) + "行的销售数量必须大于0");
            }
            BigDecimal orderPrice = body.getOrderPrice();
            if (orderPrice == null || orderPrice.doubleValue() < 0) {
                throw new RuntimeException("第" + (i + 1) + "行的销售单价必须大于等于0");
            }
            // 构建需要修改的销售订单子表对象
            SalOrderBody updateOrderBody = new SalOrderBody();
            updateOrderBody.setOrderBodyId(body.getOrderBodyId());
            updateOrderBody.setInventoryId(body.getInventoryId());
            updateOrderBody.setOrderNumber(orderNumber);
            updateOrderBody.setOrderPrice(orderPrice);
            updateOrderBody.setOrderTotal(orderNumber.multiply(orderPrice));
            total = total.add(updateOrderBody.getOrderTotal());
            updateOrderBodyList.add(updateOrderBody);
        }
        // 构建需要修改的销售订单对象
        SalOrder updateOrder = new SalOrder();
        updateOrder.setOrderId(order.getOrderId());
        updateOrder.setOrderName(order.getOrderName());
        updateOrder.setTotal(total);
        // 销售订单执行修改
        boolean ret = updateById(updateOrder);
        if (!ret) {
            throw new RuntimeException("修改销售订单失败");
        }
        // 销售订单子表执行批量修改
        List<BatchResult> results = orderBodyMapper.updateById(updateOrderBodyList);
        if (CollUtil.isEmpty(results)) {
            throw new RuntimeException("修改销售订单子表失败");
        }
        return true;
    }

    @Override
    public boolean commitOrder(List<Long> orderIdList) {
        // select * from sal_order where order_id in (?, ?, ? ...)
        List<SalOrder> orderList = getBaseMapper().selectBatchIds(orderIdList);
        List<SalOrder> updateOrderList = new ArrayList<>();
        for (SalOrder order : orderList) {
            if (!"0".equals(order.getApproveStatus())) {
                throw new RuntimeException("序号" + order.getOrderId() + "为的数据订单状态不为初始，不能提交");
            }
            // 构建需要提交的销售订单对象
            SalOrder updateOrder = new SalOrder();
            updateOrder.setOrderId(order.getOrderId());
            updateOrder.setApproveStatus("1");
            updateOrderList.add(updateOrder);
        }
        // 执行提交： update sal_order set approve_status = '1' where order_id = ?
        List<BatchResult> results = getBaseMapper().updateById(updateOrderList);
        if (CollUtil.isEmpty(results)) {
            throw new RuntimeException("提交失败");
        }
        return true;
    }

    @Override
    public boolean recallOrder(List<Long> orderIdList) {
        // select * from sal_order where order_id in (?, ?, ? ...)
        List<SalOrder> orderList = getBaseMapper().selectBatchIds(orderIdList);
        List<SalOrder> updateOrderList = new ArrayList<>();
        for (SalOrder order : orderList) {
            if (!"1".equals(order.getApproveStatus())) {
                throw new RuntimeException("序号" + order.getOrderId() + "为的数据订单状态不为审批中，不能撤回");
            }
            // 构建需要提交的销售订单对象
            SalOrder updateOrder = new SalOrder();
            updateOrder.setOrderId(order.getOrderId());
            updateOrder.setApproveStatus("0");
            updateOrderList.add(updateOrder);
        }
        // 执行提交： update sal_order set approve_status = '1' where order_id = ?
        List<BatchResult> results = getBaseMapper().updateById(updateOrderList);
        if (CollUtil.isEmpty(results)) {
            throw new RuntimeException("撤回失败");
        }
        return true;
    }

    @Override
    public boolean approveOrder(SalOrder order) {
        SalOrder salOrder = getOrderById(order.getOrderId());
        if (salOrder == null) {
            throw new RuntimeException("单据不存在，请刷新后重试");
        }
        // 校验订单状态
        if (!"1".equals(salOrder.getApproveStatus())) {
            throw new RuntimeException("只有订单状态为审批中的数据才可以审批");
        }
        String approveResult = order.getApproveResult();
        if (StrUtil.isBlank(approveResult)) {
            throw new RuntimeException("审批结果不能为空");
        }
        SalOrder approveOrder = new SalOrder();
        approveOrder.setOrderId(order.getOrderId());
        approveOrder.setApprover(SecurityUtils.getLoginUser().getUsername());
        approveOrder.setApproveTime(LocalDateTime.now());
        approveOrder.setApproveOpinion(order.getApproveOpinion());
        switch (approveResult) {
            case "pass" -> {
                //审批通过
                // 将订单状态改为审批通过
                approveOrder.setApproveStatus("2");
                // 自动生成一张销售出库单
                boolean inoutRet = inoutService.genInoutByOrder(salOrder);
                if (!inoutRet) {
                    throw new RuntimeException("生成下游单据[销售出库单]失败");
                }
            }
            case "nopass" -> {
                //审批不通过：审批意见必填
                if (StrUtil.isBlank(approveOrder.getApproveOpinion())) {
                    throw new RuntimeException("审批意见不能为空");
                }
                // 将订单状态改为审批不通过
                approveOrder.setApproveStatus("3");

            }
            case "reject" -> {
                //驳回：审批意见必填
                if (StrUtil.isBlank(approveOrder.getApproveOpinion())) {
                    throw new RuntimeException("审批意见不能为空");
                }
                // 确认后将订单状态改为初始
                approveOrder.setApproveStatus("0");
            }
        }
        // 执行审批： update sal_order set approve_status = ?, approver = ?, approve_time = ?, approve_opinion = ? where order_id = ?
        return getBaseMapper().approveOrder(approveOrder);
    }

    @Override
    public boolean unapproveOrder(SalOrder order) {
        SalOrder salOrder = getById(order.getOrderId());
        if (salOrder == null) {
            throw new RuntimeException("单据不存在，请刷新后重试");
        }
        // 校验订单状态
        if (!"2".equals(salOrder.getApproveStatus()) && !"3".equals(salOrder.getApproveStatus())) {
            throw new RuntimeException("只有订单状态为审批通过或不通过的数据才可以弃审");
        }
        // 删除下游销售出库单
        boolean inoutRet = inoutService.delInoutByOrder(salOrder);
        if (!inoutRet) {
            throw new RuntimeException("删除下游单据[销售出库单]失败");
        }
        // 构建需要弃审的销售订单对象
        SalOrder approveOrder = new SalOrder();
        approveOrder.setOrderId(order.getOrderId());
        approveOrder.setApprover(null);
        approveOrder.setApproveTime(null);
        approveOrder.setApproveOpinion(null);
        approveOrder.setApproveStatus("1");
        // 执行弃审： update sal_order set approve_status = '1', approver = null, approve_time = null, approve_opinion = null where order_id = ?
        return getBaseMapper().approveOrder(approveOrder);
    }

    /**
     * 生成销售订单编号
     * @return 编号
     */
    private String genOrderCode() {
        // 根据指定格式获取当天字符串
        String today = DateUtil.format(new Date(), "yyyyMMdd");
        // 查询当天最大流水号记录
        String maxCode = getBaseMapper().selectMaxCode(today);
        if (StrUtil.isBlank(maxCode)) {
            // 当天没有流水号，直接返回
            return "ORDER" + today + "001";
        } else {
            // 截取最后三位
            String oldCode = maxCode.substring(maxCode.length() - 3);
            // 流水号+1并补0
            String newCode = String.format("%03d", Integer.parseInt(oldCode) + 1);
            // 返回新的流水号
            return "ORDER" + today + newCode;
        }
    }
}
